package io.nutz.nutzsite.module.sys.controllers;

import io.nutz.nutzsite.common.base.Globals;
import io.nutz.nutzsite.common.base.Result;
import io.nutz.nutzsite.common.listener.WebSessionListener;
import io.nutz.nutzsite.common.manager.AsyncManager;
import io.nutz.nutzsite.common.manager.factory.AsyncFactory;
import io.nutz.nutzsite.common.socket.WkWsHandler;
import io.nutz.nutzsite.common.utils.DESCryption;
import io.nutz.nutzsite.common.utils.ShiroUtils;
import io.nutz.nutzsite.common.utils.Toolkit;
import io.nutz.nutzsite.module.sys.models.User;
import io.nutz.nutzsite.module.sys.services.UserService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.nutz.dao.Cnd;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Fail;
import org.nutz.mvc.annotation.GET;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.POST;
import org.nutz.mvc.annotation.Param;

/**
 * @author haiming
 */
@At("/login")
@IocBean
public class LoginController {
	private static final Log log = Logs.get();
    @Inject
    private UserService userService;
    /*@Inject
    private UserOnlineService userOnlineService;*/
    @Inject
    private AsyncFactory asyncFactory;
    @Inject("refer:shiroWebSessionManager")
    private DefaultWebSessionManager webSessionManager;
    @Inject
    private WebSessionListener webSessionListener;


    @Inject("refer:$ioc")
    protected Ioc ioc;
    @GET
    @At({"","/loginPage"})
    @Ok("re")
    public String loginPage(  HttpServletRequest req) {
        if (ShiroUtils.isAuthenticated()) {
            return ">>:/index";
        }
        return "th:/login.html";
    }


    @Ok("json")
    @Fail("http:500")
    @POST
    @At("/login")
    public Result login(@Param("username")String username,
                        @Param("password")String password,
                        @Param("macaddr")String macaddr,
                        @Param("rememberMe")boolean rememberMe,
                        @Param("validateCode")String validateCode,
                        HttpServletRequest req,
                        HttpSession session) {
        
        try {
            Subject subject = SecurityUtils.getSubject();
            ThreadContext.bind(subject);
            subject.login(new UsernamePasswordToken(username,password,rememberMe));
            User user =ShiroUtils.getSysUser();
            user.setMacaddr(macaddr);
            ShiroUtils.setSysUser(user);
            //=====================================
            Session session2=subject.getSession();
            session2.setAttribute("fcre_uid",username);
            AsyncManager.me().execute(asyncFactory.addOnline(user, session2,req));
            AsyncManager.me().execute(asyncFactory.recordLogininfor(user.getId(), true,req,"登录成功"));

            return Result.success("login.success");
        } catch (LockedAccountException e) {
            AsyncManager.me().execute(asyncFactory.recordLogininfor(username, false,req,"账号锁定"));
            return Result.error(3, "login.error.locked");
        } catch (UnknownAccountException e) {
            AsyncManager.me().execute(asyncFactory.recordLogininfor(username, false,req,"用户不存在"));
            return Result.error(4, "login.error.user");
        } catch (AuthenticationException e) {
            AsyncManager.me().execute(asyncFactory.recordLogininfor(username, false,req,"密码错误"));
            return Result.error(5, "login.error.pwd");
        /*} catch (BadPaddingException e) {
            AsyncManager.me().execute(asyncFactory.recordLogininfor(username, false,req,"密码错误"));
            return Result.error(5, "login.error.pwd");*/
        } catch (Exception e) {
            e.printStackTrace();
            AsyncManager.me().execute(asyncFactory.recordLogininfor(username, false,req,"登录系统异常"));
            return Result.error(6, "login.error.system");
        }
    }

    @At
    @Ok("re")
    public String logout() {
        Subject subject = SecurityUtils.getSubject();
        while(Lang.isNotEmpty(subject) &&  subject.isAuthenticated()) {
        	User user=ShiroUtils.getSysUser();
        	user.setSessionId("");
        	user.setUserOnline(false);
        	userService.update(user);
            subject.logout();
        }
        //return ">>:/adm";
        return ">>:/";
    }
    @At
    @Ok("re")
    public String kdlogout() {
        Subject subject = SecurityUtils.getSubject();
        while(Lang.isNotEmpty(subject) &&  subject.isAuthenticated()) {
        	User user=ShiroUtils.getSysUser();
        	user.setSessionId("");
        	user.setUserOnline(false);
        	userService.update(user);
            subject.logout();
        }
        return ">>:/kc";
    }
    @At
    @Ok("http:403")
    public void unauth() {

    }
    @Ok("json")
    @Fail("http:500")
    @POST
    @At
    public Result kdlogin(@Param("username")String username,
                        @Param("password")String password,
                        @Param("macaddr")String macaddr,
                        @Param("rememberMe")boolean rememberMe,
                        @Param("validateCode")String validateCode,
                        HttpServletRequest req,
                        HttpSession session) {
        
        if(Boolean.valueOf(Globals.getConfig("login.captcha"))){
            // session是否有效
            if (session == null) {
                return Result.error("当前会话已过期,请刷新后重试");
            }
            // 比对验证码
            String _captcha = (String) session.getAttribute(Toolkit.captcha_attr);
            if (Strings.isBlank(_captcha) || !Toolkit.checkCaptcha(_captcha,validateCode)) {
                return Result.error("验证码错误");
            }
        }
        try {
            Subject subject = SecurityUtils.getSubject();
            ThreadContext.bind(subject);
            //RSA解密
            //password = RSAUtils.decrypt(password, Globals.getPrivateKey());

            subject.login(new UsernamePasswordToken(username,password,rememberMe));
            User user =ShiroUtils.getSysUser();
            user.setMacaddr(macaddr);
            ShiroUtils.setSysUser(user);
            //user.setSession(session);
            //=========websocket与Httpsession建立联系,wsid将记录到Httpsession中。====================
            WkWsHandler myWsHandler=ioc.get(WkWsHandler.class);
            myWsHandler.setHttpSession(session);
            //=====================================
            Session session2=subject.getSession();
            session2.setAttribute("fcre_uid",username);
            AsyncManager.me().execute(asyncFactory.addOnline(user, session2,req));
          //如果启用了用户唯一登录功能
            if ("1".equals(Globals.getConfig("shiro.session.maxSession"))) {
                try {
                    User oldUser = userService.fetch(Cnd.where("id", "=", user.getId()));
                    if (oldUser != null && !Strings.sNull(oldUser.getSessionId()).equals(session.getId())) {
                        Session oldSession = webSessionManager.getSessionDAO().readSession(oldUser.getSessionId());
                        if (oldSession != null) {
                            //wkNotifyService.offline(oldUser.getLoginname(), oldUser.getLoginSessionId());//通知另外一个用户被踢下线
                            //oldSession.stop();
                            //webSessionManager.getSessionDAO().delete(oldSession);
                        	log.debug("\r\noldsession exist...\r\n");
                        }
                    }
                } catch (Exception e) {

                }
            }
            AsyncManager.me().execute(asyncFactory.recordLogininfor(user.getId(), true,req,"登录成功"));
            //userService.recordLoginInfo(user);
            //AsyncManager.me().execute(asyncFactory.syncSessionToDb(session));

            return Result.success("");
        } catch (LockedAccountException e) {
            AsyncManager.me().execute(asyncFactory.recordLogininfor(username, false,req,"账号锁定"));
            return Result.error(3, "login.error.locked");
        } catch (UnknownAccountException e) {
            AsyncManager.me().execute(asyncFactory.recordLogininfor(username, false,req,"用户不存在"));
            return Result.error(4, "login.error.user");
        } catch (AuthenticationException e) {
            AsyncManager.me().execute(asyncFactory.recordLogininfor(username, false,req,"密码错误"));
            return Result.error(5, "login.error.pwd");
        /*} catch (BadPaddingException e) {
            AsyncManager.me().execute(asyncFactory.recordLogininfor(username, false,req,"密码错误"));
            return Result.error(5, "login.error.pwd");*/
        } catch (Exception e) {
            e.printStackTrace();
            AsyncManager.me().execute(asyncFactory.recordLogininfor(username, false,req,"登录系统异常"));
            return Result.error(6, "login.error.system");
        }
    }
}
